package com.df.tv.launcher.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.GridView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.df.tv.launcher.R;
import com.df.tv.launcher.activity.MainActivity;
import com.df.tv.launcher.activity.MainActivity.onAppRefreshListener;
import com.df.tv.launcher.adapter.ApplicationAdapter;
import com.df.tv.launcher.model.AppMgrMod;
import com.df.tv.launcher.params.ComParams;
import com.df.tv.tm.aidl.AppInfoEntity;
import com.df.tv.tm.aidl.AppMgrService;
import com.telecom.tv189.comlib.util.Log;
import com.telecom.tv189.comlib.util.TV189Toast;
import com.telecom.tv189.comlib.view.XUtilsImageView;

/**
 * Application list display interface
 * 
 * @author liubaolin
 * 
 */
public class ApplicationFragment extends Fragment implements OnFocusChangeListener, OnItemSelectedListener,
        OnItemClickListener, OnKeyListener {
    private static final String TAG = "ApplicationFragment";
    private GridView mGridView;
    private RelativeLayout mFoucusLayout;
    private TextView mFocusTextView;
    private XUtilsImageView mFocusImageView;
    private ApplicationAdapter mApplicationAdapter;
    private Activity mActivity;
    private int mGridViewSelectedItem = 0;

    private static final int SET_FIRST_ITEM_SELECTED_FOR_GRIDVIEW = 0x00;
    private static final int SET_TO_UPDATE_APPLICATION_PAGE = 0x01;
    private static final int SET_NO_APP_LIST_REQUESTED = 0x02;
    private static final int FLAG_REQUEST_TO_TOAST_MESSAGE = 0x03;
    private static final int START_TM_APP_MAGR_ACTIVITY = 0x04;

    private static final int REQUSET_TO_INSTALL_APP = 200;
    private static final int RESULT_FOR_INSTALL_APP_SUCCESS = 201;
    private static final int RESULT_FOR_INSTALL_APP_FAILURE = 202;

    private static final int REQUEST_TO_UNINSTALL_APP = 300;
    private static final int RESULT_FOR_UNINSTALL_APP_SUCCESS = 301;
    private static final int RESULT_FOR_UNINSTALL_APP_FAILURE = 302;

    private static final int THREAD_SLEEP_INTERVAL_TIME = 1000;

    private static final String PACKAGE_NAME_FOR_APP = "package_name";
    private String mPackageName = "";
    private List<AppInfoEntity> mApplicationList = new ArrayList<AppInfoEntity>();
    private AppMgrService mAppService = null;
    private ServiceBinder mAppServiceConnection = null;
    private MyThread mGetAPPListThread = null;
    private boolean isNeedSetGridViewFirstItemFocus = true;

    private boolean isStop = true;
    private AppMgrMod appMgrMod = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "-->onCreate");
        super.onCreate(savedInstanceState);

        appMgrMod = new AppMgrMod();
        mGetAPPListThread = new MyThread();
        mGetAPPListThread.start();

        setOnAppRefreshListener();
    }

    @Override
    public void onAttach(Activity activity) {
        Log.d(TAG, "-->onAttach");
        super.onAttach(activity);
        mActivity = activity;

    }

    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case SET_TO_UPDATE_APPLICATION_PAGE:
                setAdapter();
                unBindService();
                break;
            case SET_NO_APP_LIST_REQUESTED:

                TV189Toast.makeText(mActivity, TV189Toast.CODE_APP_GETLIST_ERR, "No app requested...",
                        TV189Toast.LENGTH_SHORT).show();
                break;
            case SET_FIRST_ITEM_SELECTED_FOR_GRIDVIEW:

                setGridViewFirstItemZoomOut();
                break;
            case FLAG_REQUEST_TO_TOAST_MESSAGE:

                String message = (String) msg.obj;
                if (!TextUtils.isEmpty(message)) {
                    //												TV189Toast.makeText(mActivity, TV189Toast.CODE_UNDEFINED, message, TV189Toast.LENGTH_SHORT).show();
                }
                break;
            case START_TM_APP_MAGR_ACTIVITY:
                //to do uninstall selected app.
                startAppMgrActivity(ComParams.FLAG_FOR_UNINSTALL_APPLICATION, REQUEST_TO_UNINSTALL_APP);
                break;
            default:
                break;
            }
        };
    };

    public View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup container,
            Bundle savedInstanceState) {
        Log.d(TAG, "-->onCreateView");
        View view = (RelativeLayout) inflater.inflate(R.layout.activity_main, container, false);
        mGridView = (GridView) view.findViewById(R.id.gv_app_list);
        mFoucusLayout = (RelativeLayout) view.findViewById(R.id.llyt_focus);
        mFocusImageView = (XUtilsImageView) view.findViewById(R.id.img_app);
        mFocusTextView = (TextView) view.findViewById(R.id.tv_app_name);

        mApplicationAdapter = new ApplicationAdapter(mActivity, mApplicationList);
        mGridView.setAdapter(mApplicationAdapter);

        mGridView.setOnKeyListener(this);
        mGridView.setOnItemClickListener(this);
        mGridView.setOnItemSelectedListener(this);
        mGridView.setOnFocusChangeListener(this);

        return view;
    };

    /**
     * Regeister listener.
     */
    private void setOnAppRefreshListener() {
        Log.d(TAG, "-----------------onRefresh");
        if (mActivity instanceof MainActivity) {
            ((MainActivity) mActivity).setOnRefreshListener(new onAppRefreshListener() {

                @Override
                public void onRefresh(int reqCode, int resCode, Intent data) {
                    if (reqCode == REQUSET_TO_INSTALL_APP || reqCode == REQUEST_TO_UNINSTALL_APP) {
                        refreshAppList(reqCode, resCode, data);
                    }
                }
            });
        }
    }

    /**
     * Refresh application display interface
     * 
     * @param requestCode
     * @param resultCode
     * @param packageName
     */
    private void refreshAppList(int requestCode, int resultCode, Intent data) {

        if (data == null) { return; }
        mPackageName = data.getStringExtra(PACKAGE_NAME_FOR_APP);

        if (TextUtils.isEmpty(mPackageName)) {
            //TV189Toast.makeText(mActivity, TV189Toast.CODE_UNDEFINED, R.string.package_is_empty, TV189Toast.LENGTH_SHORT).show();
            return;
        }

        AppInfoEntity appInfoEntity = getOperatedAPPInfoByPName(mPackageName);

        if (appInfoEntity == null) {
            //TV189Toast.makeText(mActivity, TV189Toast.CODE_UNDEFINED, R.string.package_is_not_exist, TV189Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode) {
        case REQUSET_TO_INSTALL_APP:

            switch (resultCode) {
            case RESULT_FOR_INSTALL_APP_SUCCESS:

                break;
            case RESULT_FOR_INSTALL_APP_FAILURE:

                break;
            default:
                break;
            }
            break;

        case REQUEST_TO_UNINSTALL_APP:

            switch (resultCode) {
            case RESULT_FOR_UNINSTALL_APP_SUCCESS:
                if (mFoucusLayout != null) {
                    mFoucusLayout.setVisibility(View.GONE);
                }

                mApplicationList.remove(appInfoEntity);
                mApplicationAdapter.notifySetDataChanged(mApplicationList);

                break;
            case RESULT_FOR_UNINSTALL_APP_FAILURE:

                break;
            default:
                break;
            }
            break;
        default:
            break;
        }
    }

    /**
     * Set apdater.
     */
    private void setAdapter() {
        if (mApplicationAdapter != null) {
            isNeedSetGridViewFirstItemFocus = false;

            mApplicationAdapter.notifySetDataChanged(mApplicationList);
        }
        else {
            isNeedSetGridViewFirstItemFocus = true;

            mApplicationAdapter = new ApplicationAdapter(mActivity, mApplicationList);
            mGridView.setAdapter(mApplicationAdapter);
        }

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Log.d(TAG, "-->onItemClick");
        startAppMgrActivity(ComParams.FLAG_FOR_INSTALL_APPLICATION, REQUSET_TO_INSTALL_APP);
    }

    /**
     * Get current active application info.
     * 
     * @param packageName
     * @return
     */
    private AppInfoEntity getOperatedAPPInfoByPName(String packageName) {
        AppInfoEntity appEntity = null;
        if (TextUtils.isEmpty(packageName)) {
            //TV189Toast.makeText(mActivity, TV189Toast.CODE_UNDEFINED, R.string.package_is_empty, TV189Toast.LENGTH_SHORT).show();
            return null;
        }
        if (!mApplicationList.isEmpty()) {
            for (AppInfoEntity appBean : mApplicationList) {
                if (packageName.equalsIgnoreCase(appBean.getApkname())) {
                    appEntity = appBean;
                    break;
                }
            }
        }
        return appEntity;
    }

    /* (non-Javadoc)
     * @see android.support.v4.app.Fragment#onStart()
     */
    @Override
    public void onStart() {
        super.onStart();
        if (isStop) {
            mGetAPPListThread = new MyThread();
            mGetAPPListThread.start();
        }
        Log.d(TAG, "-->onStart");
    }

    @Override
    public void onResume() {
        Log.d(TAG, "-->onResume");
        super.onResume();
        if (!mApplicationList.isEmpty() && isNeedSetGridViewFirstItemFocus) {
            mHandler.sendEmptyMessage(SET_FIRST_ITEM_SELECTED_FOR_GRIDVIEW);
        }
    }

    /**
     * Set focus Zoom out into front of Grid view.
     */
    private void setGridViewFirstItemZoomOut() {
        AppInfoEntity appBean0 = mApplicationList.get(0);

        if (appBean0 == null) { return; }

        mGridView.setFocusable(true);
        mGridView.requestFocus();

        mApplicationAdapter.setImageView(0, mFocusImageView, appBean0, true);
        if (appBean0.isLocalApp()) {
            mFocusTextView.setVisibility(View.VISIBLE);
            mFocusTextView.setText(TextUtils.isEmpty(appBean0.getAppname()) ? "Default App" : appBean0.getAppname());
        }
        else {
            mFocusTextView.setVisibility(View.INVISIBLE);
        }
        mFoucusLayout.setX(mGridView.getChildAt(0).getX() + mGridView.getX() + mGridView.getChildAt(0).getWidth() / 2
                - mFoucusLayout.getWidth() / 2);
        mFoucusLayout.setY(mGridView.getChildAt(0).getY() + mGridView.getY() + mGridView.getChildAt(0).getHeight() / 2
                - mFoucusLayout.getHeight() / 2);
        mFoucusLayout.setVisibility(View.VISIBLE);
        Log.d(TAG, mFocusImageView.getResources().toString());

    }

    @Override
    public void onPause() {
        Log.d(TAG, "-->onPause");
        super.onPause();

        isNeedSetGridViewFirstItemFocus = false;
    }

    @Override
    public void onStop() {
        Log.d(TAG, "-->onStop");
        super.onStop();
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "-->onDestroy");
        super.onDestroy();
        isNeedSetGridViewFirstItemFocus = true;

        if (!mApplicationList.isEmpty()) {
            mApplicationList.clear();
        }
        if (mGetAPPListThread != null && mGetAPPListThread.isAlive()) {
            mGetAPPListThread.setStop(true);
            mGetAPPListThread = null;
        }
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        Log.d(TAG, "-->onFocusChange");
        if (!hasFocus) {
            mGridView.setSelection(-1);
        }

    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        Log.d(TAG, "-->onItemSelected");
        //记录当前高亮选中的某个应用的位置
        mGridViewSelectedItem = position;
        mGridView.setFocusable(true);
        mGridView.requestFocus();

        AppInfoEntity appBean = mApplicationList.get(position);
        //if not have icon,should be set transparent 
        mFocusImageView.setImageBitmap(null);
        mApplicationAdapter.setImageView(position, mFocusImageView, appBean, true);

        if (appBean.isLocalApp()) {
            mFocusTextView.setVisibility(View.VISIBLE);
            mFocusTextView.setText(TextUtils.isEmpty(appBean.getAppname()) ? "Default App" : appBean.getAppname());
        }
        else {
            mFocusTextView.setVisibility(View.INVISIBLE);
        }
        mFoucusLayout.setX(view.getX() + parent.getX() + view.getWidth() / 2 - mFoucusLayout.getWidth() / 2);
        mFoucusLayout.setY(view.getY() + parent.getY() + view.getHeight() / 2 - mFoucusLayout.getHeight() / 2);
        mFoucusLayout.setVisibility(View.VISIBLE);

    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        mFoucusLayout.setVisibility(View.GONE);
    }

    /**
     * Create inner class for service binder.
     * 
     * @author pc1
     * 
     */
    private class ServiceBinder implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mAppService = AppMgrService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAppService = null;
        }

    }

    /**
     * Trigger get application list service.
     */
    private boolean startGetAppService() {
        mAppServiceConnection = new ServiceBinder();
        Intent intent = new Intent(ComParams.GET_APP_SERVICE_ACITON);
        boolean result = false;
        try {
            result = mActivity.bindService(intent, mAppServiceConnection, Context.BIND_AUTO_CREATE);
        } catch (SecurityException e) {
            Log.d(TAG, e.getLocalizedMessage());
            Message msg = Message.obtain();
            msg.what = FLAG_REQUEST_TO_TOAST_MESSAGE;
            msg.obj = e.getMessage();
            mHandler.sendMessage(msg);

            mGetAPPListThread.setStop(true);

        }
        return result;
    }

    /**
     * Create A thread to get app data from background service.
     * 
     * @author pc1
     * 
     */

    private class MyThread extends Thread {

        /* (non-Javadoc)
         * @see java.lang.Thread#start()
         */
        @Override
        public synchronized void start() {
            Log.d(TAG, "-->getAllApps Thread start()");
            setStop(false);
            super.start();

        }

        public void setStop(boolean stop) {
            isStop = stop;
        }

        public void run() {
            while (!isStop) {
                if (mAppService == null && !startGetAppService()) {
                    try {
                        //						Log.d(TAG, "-->getAllApps Thread sleep(100)");
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    continue;
                }
                if (mAppService == null) {
                    try {
                        //						Log.d(TAG, "-->mAppService==null Thread sleep(100)");
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    continue;
                }

                try {
                    mApplicationList = mAppService.getAllAppInfos();
                    if (mApplicationList != null && !mApplicationList.isEmpty()) {
                        PackageManager pm = mActivity.getPackageManager();
                        for (AppInfoEntity appItem : mApplicationList) {
                            //is local app will be set icon bitmap,
                            //if it's from server should be use url to show icon,if url is empty should be set icon bitmap too.
                            if (appItem.isLocalApp()
                                    || (!appItem.isLocalApp() && TextUtils.isEmpty(appItem.getImg1()) && TextUtils
                                            .isEmpty(appItem.getImg2()))) {
                                PackageInfo pInfo = appMgrMod.checkAppExist(mActivity, appItem.getApkname());
                                if (pInfo != null) {
                                    try {
                                        Resources res = pm.getResourcesForApplication(pInfo.applicationInfo);
                                        Bitmap icon = BitmapFactory.decodeResource(res, pInfo.applicationInfo.icon);
                                        appItem.setIconBitmap(icon);
                                    } catch (NameNotFoundException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                    }

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                if (!mApplicationList.isEmpty()) {
                    mHandler.sendEmptyMessage(SET_TO_UPDATE_APPLICATION_PAGE);
                }
                else {
                    mHandler.sendEmptyMessage(SET_NO_APP_LIST_REQUESTED);
                }
                isStop = true;
                break;

            }

        };
    }

    /**
     * Unbind service and cut connection.
     */
    private void unBindService() {
        mActivity.unbindService(mAppServiceConnection);
        mAppService = null;
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        Log.d(TAG, "keycode=" + keyCode);
        if (event.getAction() == KeyEvent.ACTION_UP) {
            switch (keyCode) {
            case KeyEvent.KEYCODE_MENU:
                mHandler.sendEmptyMessage(START_TM_APP_MAGR_ACTIVITY);
                return true;

            default:
                break;
            }
        }
        return false;
    }

    private void startAppMgrActivity(int doAction, int requestCode) {
        if (mApplicationList != null && mGridViewSelectedItem >= 0 && mGridViewSelectedItem < mApplicationList.size()) {
            Intent intent = new Intent();
            intent.setAction(ComParams.APP_REDIRECT_ACTION);
            intent.putExtra(ComParams.APP_APPLICATION_ACTION_TYPE, doAction);
            //intent.putExtra(ComParams.APP_APPLICATION_ACTION_DATA, mApplicationList.get(mGridViewSelectedItem));

            AppInfoEntity appInfo = mApplicationList.get(mGridViewSelectedItem);
            //防止出现transationToLargeException
            if (appInfo.getIconBitmap() != null) {
                appInfo.setIconBitmap(null);
            }
            intent.putExtra(ComParams.APP_APPLICATION_ACTION_DATA, appInfo);

            getActivity().startActivityForResult(intent, requestCode);
        }
    }
}
